package com.crazymakercircle.imClient.sender;

import com.crazymakercircle.im.common.bean.User;
import com.crazymakercircle.im.common.bean.msg.ProtoMsg;
import com.crazymakercircle.imClient.client.ClientSession;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 在Netty中，无论是入站操作还是出站操作，都有两大特点
 * 1. 同一条通道的所有出/入站处理都是串行的，而不是并行的。换句话说，同一条通道上所有出/入站处理都会在它所绑定的EventLoop线程上执行。
 * 既然只有一个线程负责，那就只有串行的可能。
 * 2. Netty的一个出/入站操作不是一次的单一Handler业务处理器操作，而是流水线上的一系列的出/入站处理流程。只有整个流程都处理完出/入站操作才真正处理完成。
 */
@Data
@Slf4j
public abstract class BaseSender {

    /**
     * 用户信息
     */
    private User user;

    /**
     * 客户端session
     */
    private ClientSession session;

    public boolean isConnected() {
        if (null == session) {
            log.info("session is null");
            return false;
        }

        return session.isConnected();
    }

    public boolean isLogin() {
        if (null == session) {
            log.info("session is null");
            return false;
        }

        return session.isLogin();
    }

    public void sendMsg(ProtoMsg.Message message) {
        if (null == getSession() || !isConnected()) {
            log.info("连接还没成功");
            return;
        }

        Channel channel = getSession().getChannel();
        // 立即返回ChannelFuture异步任务实例，真正的TCP写入操作还未执行
        ChannelFuture f = channel.writeAndFlush(message);
        f.addListener(future -> {
            // 回调
            if (future.isSuccess()) {
                sendSucced(message);
            } else {
                sendfailed(message);

            }
        });

        /*try {
            f.sync();
        } catch (InterruptedException e) {

            e.printStackTrace();
            sendException(message);
        }*/
    }

    protected void sendSucced(ProtoMsg.Message message) {
        log.info("发送成功");

    }

    protected void sendfailed(ProtoMsg.Message message) {
        log.info("发送失败");
    }
}
